package device

import (
	"adai.design/jarvis/common/log"
	"adai.design/jarvis/server"
	"github.com/gorilla/websocket"
	"net/http"
)

type PkgObserver interface {
	DevicePkgHandle(pkg *MessagePkg)
}

type receptions struct {
	// 在线设备列表
	devices map[string]*reception

	online  chan *reception
	offline chan *reception

	// 传输的数据包
	rpkg chan *MessagePkg
	spkg chan *MessagePkg

	observers []PkgObserver

	// websocket server
	upgrader websocket.Upgrader
	end      chan bool
}

func (rs *receptions) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	c, err := rs.upgrader.Upgrade(response, request, nil)
	if err != nil {
		log.Error("upgrader: %s", err)
		return
	}
	r := newReception(c)
	go r.start(rs)
}

func (rs *receptions) start() {
	for {
		select {

		// 设备在线
		case w, ok := <-rs.online:
			if ok {
				if old, ok := rs.devices[w.register.Id]; ok {
					if old != w {
						old.stop()
					}
				}
				log.Warn("device(%s) online", w.register.Id)
				rs.devices[w.register.Id] = w
			}

		// 设备离线
		case w, ok := <-rs.offline:
			if ok {
				if v, ok := rs.devices[w.register.Id]; ok {
					if v == w {
						log.Warn("device(%s) offline", w.register.Id)
						delete(rs.devices, w.register.Id)

						// 向家庭中心发送设备离线消息
						pkg := &MessagePkg{
							HomeId: v.register.HomeId,
							DevId:  v.register.Id,
							Msg: &Message{
								Path:   MsgPathContainerInfo,
								Method: MsgMethodPut,
								State:  ContainerStateOffline,
							},
						}
						rs.rpkg <- pkg

					}
				}
				w.stop()
			}

		// 向设备发送的消息
		case pkg, ok := <-rs.spkg:
			if ok {
				if dev, ok := rs.devices[pkg.DevId]; ok {
					dev.task <- pkg.Msg
				}
			}

		// 设备发送回来的中转消息,
		case pkg, ok := <-rs.rpkg:
			if ok {
				for _, observer := range rs.observers {
					observer.DevicePkgHandle(pkg)
				}
			}
		}
	}
}

var workers = &receptions{
	devices: make(map[string]*reception, 0),
	online:  make(chan *reception, 10),
	offline: make(chan *reception, 10),
	rpkg:    make(chan *MessagePkg, 50),
	spkg:    make(chan *MessagePkg, 50),
}

func SendPkg(pkg *MessagePkg) error {
	if workers.spkg != nil {
		workers.spkg <- pkg
	}
	return nil
}

// 监听消息
func AddObserver(ob PkgObserver) error {
	workers.observers = append(workers.observers, ob)
	return nil
}

// 移除监听
func RemoveObserver(ob PkgObserver) error {
	workers.observers = append(workers.observers, ob)
	return nil
}

func init() {
	server.AddService("device", workers)
}

func Start(end chan bool) {
	workers.end = end
	go workers.start()
}
